using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;


namespace WindowsApplication1
{
    public partial class Form1 : Form
    {
        [DllImport("umf.DLL", EntryPoint = "fw_init")]
        public static extern Int32 fw_init(Int16 port, Int32 baud);
        [DllImport("umf.DLL", EntryPoint = "fw_exit")]
        public static extern Int32 fw_exit(Int32 icdev);
        [DllImport("umf.Dll", EntryPoint = "fw_request")]
        public static extern Int32 fw_request(Int32 icdev, Byte _Mode, ref UInt32 TagType);
        [DllImport("umf.DLL", EntryPoint = "fw_anticoll")]
        public static extern Int32 fw_anticoll(Int32 icdev, Byte _Bcnt, ref UInt32 _Snr);
        [DllImport("umf.DLL", EntryPoint = "fw_select")]
        public static extern Int32 fw_select(Int32 icdev, UInt32 _Snr, ref Byte _Size);
        [DllImport("umf.DLL",EntryPoint="fw_card")]
        public static extern Int32 fw_card(Int32 icdev,Byte _Mode,ref UInt32 _Snr);

        [DllImport("umf.DLL", EntryPoint = "fw_config_card")]
        public static extern Int32 fw_config_card(Int32 icdev, Byte _Mode);
        [DllImport("umf.DLL",EntryPoint="fw_load_key")]
        public static extern Int32 fw_load_key(Int32 icdev,Byte _Mode,Byte _SecNr,ref Byte _NKey);
        [DllImport("umf.DLL",EntryPoint="fw_authentication")]
        public static extern Int32  fw_authentication(Int32 icdev,Byte _Mode,Byte _SecNr);
        [DllImport("umf.DLL",EntryPoint="fw_read")]
        public static extern  Int32  fw_read(Int32 icdev,Byte _Adr,ref Byte _Data);
        [DllImport("umf.DLL", EntryPoint = "fw_write")]
        public static extern  Int32  fw_write(Int32 icdev,Byte _Adr,ref Byte _Data);
        [DllImport("umf.DLL", EntryPoint = "fw_halt")]
        public static extern  Int32  fw_halt(Int32 icdev);
        [DllImport("umf.DLL", EntryPoint = "fw_changeb3")]
        public static extern Int32  fw_changeb3(Int32 icdev,Byte _SecNr,ref Byte _KeyA,ref Byte _CtrlW,Byte _Bk,
				ref Byte _KeyB);
        [DllImport("umf.DLL", EntryPoint = "fw_initval")]
        public static extern Int32 fw_initval(Int32 icdev,Byte _Adr,UInt32 _Value);
        [DllImport("umf.DLL", EntryPoint = "fw_increment")]
        public static extern Int32 fw_increment(Int32 icdev,Byte _Adr,UInt32 _Value);
        [DllImport("umf.DLL", EntryPoint = "fw_readval")]
        public  static extern Int32 fw_readval(Int32 icdev,Byte _Adr,ref UInt32 _Value);
        [DllImport("umf.DLL", EntryPoint = "fw_decrement")]
        public static extern Int32  fw_decrement(Int32 icdev,Byte _Adr,UInt32 _Value);
        [DllImport("umf.DLL", EntryPoint = "fw_restore")]
        public static extern Int32  fw_restore(Int32  icdev,Byte _Adr);
        [DllImport("umf.DLL", EntryPoint = "fw_transfer")]
        public static extern Int32  fw_transfer(Int32 icdev,Byte _Adr);
        [DllImport("umf.DLL", EntryPoint = "fw_beep")]
        public static extern Int32  fw_beep(Int32 icdev,UInt32 _Msec);
        [DllImport("umf.DLL", EntryPoint = "fw_getver")]
        public static extern  Int32 fw_getver(Int32 icdev,ref Byte buff);
        [DllImport("umf.DLL", EntryPoint = "fw_reset")]
        public static extern Int16  fw_reset(IntPtr icdev,UInt16 _Msec);
        [DllImport("umf.dll", EntryPoint = "fw_cpureset")]
        public static extern Int16 fw_cpureset(Int32 icdev, ref Byte rlen, ref Byte rdata);
        [DllImport("umf.dll", EntryPoint = "fw_pro_reset")]
        public static extern Int16 fw_pro_reset(Int32 icdev, ref Byte rlen, ref Byte rdata);
        [DllImport("umf.dll", EntryPoint = "fw_pro_commandlink")]
        public static extern Int16 fw_pro_commandlink(Int32 icdev, Byte slen, ref Byte sdata,
            ref Byte rlen, ref Byte rdata, Byte ftt, Byte fFG);
        [DllImport("umf.dll", EntryPoint = "fw_cpuapdu")]
        public static extern Int16 fw_cpuapdu(IntPtr icdev, Byte slen, ref Byte sdata, ref Byte rlen,
            ref Byte rdata);

        [DllImport("umf.DLL",EntryPoint="hex_a")]
        public static extern void hex_a(ref Byte hex, ref Byte a,Int32 len);
        [DllImport("umf.dll", EntryPoint = "a_hex")]
        public static extern void a_hex(ref Byte a, ref Byte hex, Int32 alen);
    

        //Function



        Int32 ihdev;
        Int32[] devs;//the array of handle of devices
        Int32 state;
        bool isComOpen;
        Int32 curCardtype;

        string msgstr;

        public Form1()
        {
            InitializeComponent();
            isComOpen = false;
            curCardtype = -1;
            msgstr = "";
        }

        /// <summary>
        /// Open serial port
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
          

            Byte[] revbuf=new Byte[64];
            comboBox1.Items.Clear();

            if (!isComOpen)
            {
                /*get the handle of current reader*/
                Int32 tmphdev = 0;
                if (radioButton1.Checked == true)
                {//USB
                    int i = 0;
                    do
                    {
                        tmphdev = fw_init(100, 0);
                        if (tmphdev > 0)
                        {
                            devs[i] = tmphdev;
                            string strdevs = "Reader ";
                            strdevs += i.ToString();
                            comboBox1.Items.Add(strdevs);
                            i++;
                        }

                    }
                    while (i < 100 && tmphdev > 0);

                    ihdev = devs[0];
                    comboBox1.SelectedIndex = 0;
                }
                else
                {//Serial Port
                    Int16 fport = Int16.Parse(comboBox2.SelectedIndex.ToString());

                    ihdev = fw_init(fport, 115200);//set baut rate 115200

                    if (ihdev > 0)
                    {
                        comboBox1.Items.Add("Reader 0");
                        comboBox1.SelectedIndex = 0;
                    }

                }

                if (ihdev > 0)
                {
                    ShowMsgString("Open device OK！");
                    fw_beep(ihdev, 10);
                    button1.Text = "Close device";
                    isComOpen = true;
                }
                else
                {
                    ShowMsgString("Open device failed！");
                    return;
                }

                state = fw_getver(ihdev, ref revbuf[0]);
                if (state != 0) ShowMsgString("fw_getver Error");
                else
                {
                    ShowMsgString("fw_getver OK");
                    ASCIIEncoding encod = new ASCIIEncoding();
                    ShowMsgString(encod.GetString(revbuf,0,10));
                }
            }
            else
            {//close all readers
                int i = 0;
                while (devs[i] > 0)
                {
                    fw_exit(devs[0]);
                    devs[i] = 0;
                    i++;
                }

                if (ihdev > 0)
                    fw_exit(ihdev);

                ihdev = 0;

                comboBox1.Items.Clear();
                button1.Text = "Open device";

                isComOpen = false;
            }


        }

        private void Form1_Load(object sender, EventArgs e)
        {
            ihdev = 0;
            devs = new Int32[100];
            for (int i = 0; i < 100; i++)
                devs[i] = 0;

            this.comboBox3.SelectedIndex = 0;
    

        }


        private void button2_Click(object sender, EventArgs e)
        {
            this.Close();
        }


        private void radioButton1_Click(object sender, EventArgs e)
        {
            comboBox2.Visible = false;
        }

        private void radioButton2_Click(object sender, EventArgs e)
        {
            comboBox2.Visible = true;
            comboBox2.SelectedIndex = 0;
        }

        private void button9_Click(object sender, EventArgs e)
        {
            this.textBox2.Clear();
            msgstr = "";
        }

        /// <summary>
        /// chose special card type
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void comboBox3_SelectedIndexChanged(object sender, EventArgs e)
        {
            curCardtype = comboBox3.SelectedIndex;
            
        }
        /// <summary>
        /// show the result message
        /// </summary>
        /// <param name="msg">the message to show</param>
        private void ShowMsgString(string msg)
        {

            msgstr =  msg+msgstr;
            msgstr = "\r\n"+msgstr;
            this.textBox2.Text = msgstr;

        }

        //RF Reset
        private void button3_Click(object sender, EventArgs e)
        {
            int st;
            st = fw_reset((IntPtr)ihdev, 2);
            if (st!=0)
            {
                ShowMsgString("fw_reset Error!");
                return;
            }
            ShowMsgString("fw_reset OK!");

        }

        //Card reset
        private void button4_Click(object sender, EventArgs e)
        {
            	Int32 st;
            	switch(curCardtype)
                {
                    case 0:                                      //FCPU
                        {

                            //Find card
                            UInt32 snCard=new UInt32();
                            st = fw_config_card(ihdev, 0x41);
                            st = fw_card(ihdev, 0, ref snCard);
                            if (st != 0)
                            {
                                ShowMsgString("fw_card Error!");
                                //	return;
                            }
                            else
                            {
                                ShowMsgString("fw_card OK!");
                                ShowMsgString(snCard.ToString());
                            }

                            //Reset 
                            Byte rrlen = new Byte();
                            Byte[] rData = new Byte[256];
                            Byte[] showData = new Byte[256];
                            st = fw_pro_reset(
                                ihdev,
                                ref rrlen,
                                ref rData[0]);
                            if (st != 0)
                            {
                                ShowMsgString("fw_pro_reset Error!");
                                return;
                            }

                            ShowMsgString("fw_pro_reset OK!");
                            String strResetInfo = "Reset Information: ";

                            hex_a(ref showData[0], ref rData[0], rrlen * 2);

                            strResetInfo += System.Text.Encoding.ASCII.GetString(showData,0,rrlen*2);
                            ShowMsgString(strResetInfo);
                        }
                        break;
                    case 1:
                    case 2:
                    case 3:
                    case 4:
                        {

                            int[] arr2Lines;
                            arr2Lines = new int[5] { 1, 2, 3, 4, 5 }; 

                            Byte relen = new Byte();
                            Byte[] rebuffer=new Byte[256];
                            Byte[] rtempBuffer=new Byte[256];
                            for (int i = 0; i < 256; i++)
                            {
                                rebuffer[i] = 0;
                           //     rtempBuffer[i] = 0;
                            }

                            if (fw_cpureset(ihdev, ref relen, ref rebuffer[0])==0)
                            {
                                ShowMsgString("Reset card OK!");
                                String strResetInfo = "Reset Information: ";
                                
                                hex_a(ref rtempBuffer[0], ref rebuffer[0], 2 * relen);

                                strResetInfo += Encoding.ASCII.GetString(rtempBuffer,0,2*relen);
                                ShowMsgString(strResetInfo);
                                return;
                            }

                            ShowMsgString("Reset card error");
                            break;
                        }
                    default:
                        ShowMsgString("Have not Selected a card,Select first please!");
                        break;
                }
	
        }

        //sent command
        private void button5_Click(object sender, EventArgs e)
        {
            int st;
            //sent command
            switch (curCardtype)
            {
                case 0:                    //contactless-CPU sent command
                    {
                        byte[] srvBuffer = new byte[256];
                        byte sendlen = 75;
                        byte[] revBuffer = new byte[256];
                        byte[] revstr = new byte[512];
                        byte ftt = 9;
                        byte fFG = 60;//64;//
                        byte revlen = new byte();

                        for (int i = 0; i < 256; i++) revBuffer[i] = 0;

                        string strCommand = "";
                        strCommand = textBox1.Text.ToString();

                        int strlen = strCommand.Length;
                        if (strlen == 0)
                        {
                            MessageBox.Show("Please enter command");
                            return;
                        }
                        char[] chcmd = new char[500];
                        byte[] cmdbuf = new byte[500];


                        cmdbuf = Encoding.ASCII.GetBytes(strCommand);


                        a_hex(ref srvBuffer[0], ref cmdbuf[0], strlen / 2);
                        sendlen = (byte)(strlen / 2);


                        st = fw_pro_commandlink
                            (
                            ihdev,//value of device handle
                            sendlen,//the lenght of information to send
                            ref srvBuffer[0],//command message to send
                            ref revlen,//length of returned information
                            ref revBuffer[0],//returned information
                            ftt,//delay time ,Unit: 10ms
                            fFG//split length,should not bigger than 64
                            );
                        if (st != 0)
                        {
                            ShowMsgString("fw_pro_commandlink Error!");
                            return;
                        }

                        ShowMsgString("fw_pro_commandlink OK!");
                        string strResetInfo = "the information of returned: ";

                        hex_a(ref revstr[0], ref revBuffer[0], revlen * 2);

                        strResetInfo += Encoding.ASCII.GetString(revstr);
                        ShowMsgString(strResetInfo);
                    }
                    break;
                case 1:
                case 2:
                case 3:
                case 4:
                    {
                        byte[] sentBuffer = new byte[255];
                        byte[] realsentBuf = new byte[255];

                        byte relen = new byte();
                        byte[] reBuffer = new byte[255];
                        byte[] rtempBuffer = new byte[255];
                        for (int i = 0; i < 255; i++)
                        {
                            sentBuffer[i] = 0;
                            realsentBuf[i] = 0;
                            reBuffer[i] = 0;
                            rtempBuffer[i] = 0;
                        }

                        string m_commandInfo = "";
 
                        for (int i = 0; i < 5; i++)
                        {

                            m_commandInfo = "";

                            switch (i)
                            {
                                case 0:
                                    m_commandInfo = "00A40000022F02";
                                    break;
                                case 1:
                                    m_commandInfo = "00A4020002ef02";
                                    break;
                                case 2:
                                    m_commandInfo = "002000000412345678";
                                    break;
                                case 3:
                                    m_commandInfo = "00d600003c112233445566778811223344556677881122334455667788112233445566778811223344556677881122334455667788112233445566778811223344";
                                    break;
                                case 4:
                                    m_commandInfo = "00b000003c";
                                    break;
                                default:
                                    break;
                            }

                            int sentInfolen =m_commandInfo.Length / 2;

                            sentBuffer = Encoding.ASCII.GetBytes(m_commandInfo);

                   //         for (int j = 0; j < 255; j++) realsentBuf[j] = 0;

                            a_hex(ref realsentBuf[0], ref sentBuffer[0], sentInfolen);

                            if (fw_cpuapdu((IntPtr)ihdev, (byte)sentInfolen,
                                ref realsentBuf[0], ref relen, ref reBuffer[0]) == 0)
                            {
                                ShowMsgString("Send :");
                                ShowMsgString(m_commandInfo);


                                hex_a(ref rtempBuffer[0], ref reBuffer[0], 2 * relen);
                                ShowMsgString("Receive:");
                                ShowMsgString(Encoding.ASCII.GetString (rtempBuffer,0,2*relen));
                                continue;
                            }

                            ShowMsgString("Send command error!");
                        }
                    }
                    break;
                default:
                    ShowMsgString("Have not Selected a card,Select first please!");
                    break;
            }
        }


    }
}